package br.unifor.cct.mia.select;

import br.unifor.cct.mia.evolutionary.CobwebGenotype;
import br.unifor.cct.mia.evolutionary.Genotype;
import br.unifor.cct.mia.ga.Ga;
import br.unifor.cct.mia.util.Methods;

public class TournamentMaximize implements Select {
    private Genotype[] newPopulation;
    private int n=3;
    
    public Object execute(Object value) {
    	Object[] o = (Object[])value;
		Ga Ga = (Ga)o[0];
		
        newPopulation = new Genotype[Ga.configurations.getPopsize()+1];
        return tournament(Ga);
    }
    
    private Genotype[] tournament(Ga Ga){
    	int count = 0;
    	if ( Ga.population[Ga.configurations.getPopsize()] != null ) {//Ja adiciona o melhor
    		newPopulation[Ga.configurations.getPopsize()] = (Genotype)Ga.population[Ga.configurations.getPopsize()].clone();    		
    		newPopulation[0] = (Genotype)Ga.population[Ga.configurations.getPopsize()].clone();
    		count++;
    	}
    	
    	while ( count < newPopulation.length ) {
	    	int individuos[] = new int[n];
	    	for ( int i=0; i<n; i++ ) {
	    		int val = Methods.randIntValue(0,Ga.configurations.getPopsize()-1);
	    		while ( Methods.arrayContains(individuos,val) ) {
	    			val = Methods.randIntValue(0,Ga.configurations.getPopsize()-1);
	    		}
	    		individuos[i] = val;
	    	}
	    	
	    	Genotype select = (Genotype)Ga.population[individuos[0]];
	    	for ( int i=0; i<individuos.length; i++ ) {
	    		int index = individuos[i];
	    		Genotype ind = (Genotype)Ga.population[index];
	    		if ( ind.getFitness() > select.getFitness() ) {
	    			select = ind;
	    		} 
	    		else if ( ind.getFitness() == select.getFitness() ) {
	    			if ( select instanceof CobwebGenotype ) {
	    				if ( ((CobwebGenotype)ind).getNumCluster() < 
	    						((CobwebGenotype)select).getNumCluster()  ) {
	    					select = ind;
	    				}
	    			}
	    		}
	    	}
	    	
	    	newPopulation[count] = (Genotype)select.clone();
	    	count++;
    	}
        
        System.arraycopy(newPopulation, 0, Ga.population, 0, Ga.configurations.getPopsize()-1);
        
        return (Genotype[])Ga.population;
    }
}
